<?php
class form extends htmlwidget {
	public $elements = array();
	public $textforelements = array();
	public $legends = array();
	public $tableAttribs = array();
	public $legendStyle;
	public $formTitle;
	public $hiddenElements = array();
	public $javascript;
	public $layouts = array('vertical', 'horizontal');
	public $layout = 'vertical';
	public $legendwidth = '';	
	public $failed = 0;

	public function __construct(){
		//defaults
		$this->attributes['method'] = 'post';		
		$this->attributes['action'] = $_SERVER["REQUEST_URI"];
		
		$this->validAttributes[] = 'method';
		$this->validAttributes[] = 'action';
		$this->validAttributes[] = 'enctype';
		$this->validAttributes[] = 'onsubmit';
		$this->validAttributes[] = 'onreset';
	}
	
	public function getAction(){
		if ( isset($this->attributes['action']) && strlen ($this->attributes['action'])){
			return $this->attributes['action'];
		} else {
			return '';
		}
	}
	
	public function setAction($action){
		$this->attributes['action'] = $action;
	}	
	
	public function action($action){
		$this->setAction($action);
	}
	
	public function getLayout(){
		return $this->layout;
	}
	
	public function setLayout($layout){
		if ( in_array($layout, $this->layouts)){
			$this->layout = $layout;
		} else {
			trigger_error("Invalid Layout: [{$layout}]  for form.", E_USER_ERROR);
		}
	}
	
	public function getLegendWidth(){
		return $this->legendwidth;	
	}
	
	public function setLegendWidth($width){
		$this->legendwidth = $width;
	}

	public function getFormTitle(){
		return $this->formTitle;
	}
	
	public function setFormTitle($title){
		$this->formTitle = $title;
	}

	public function addElement($element, $legend=""){
		if( $element instanceof hiddenbox ){
			$this->hiddenElements[] = $element;
		} elseif ( $element instanceof filebox ){
			$this->elements[] = $element;
			$this->legends[] = $legend;
			$this->setAttribute('enctype', 'multipart/form-data');			
		} else {
			$this->elements[] = $element;
			$this->legends[] = $legend;
		}
	}
	
	public function add($element, $legend=''){
		$this->addElement($element, $legend);
	}
	
	public function addTextForElement($elementname, $text){
		$this->textforelements[$elementname] = $text;		
	}

	//set a class for the <td> that contain the legend of a field
	public function setLegendStyle($style){
		$this->legendStyle = $style;
	}

	public function setTableAttrib($key, $value){
		$this->tableAttribs[$key] = $value;
	}

	public function __toString(){

		//opening tag
		$this->html = '<form';
		foreach ( $this->attributes as $key => $value){
			if ( (! empty($value)) || strlen($value)){
				$this->html .= ' ' . $key . '="' . $value . '"';
			}
		}
		$this->html .= ">\n";

		//hidden elements
		if ( count($this->hiddenElements)){
			foreach ( $this->hiddenElements as $elem){
				$this->html .= $elem->getHtml() . "\n";
			}
		}

		//form title
		$this->html .= $this->formTitle . "\n";	
		
		//the form content (in a table)
		$table = new table();		
		
		//first, the table attributes
		if ( is_array($this->tableAttribs) && count($this->tableAttribs)){
			foreach ( $this->tableAttribs as $key => $value){
				$table->setAttrib($key, $value);
			}
		}

		//then the form elements
		if ( $this->layout == 'vertical'){	
			if ( strlen($this->legendwidth)){
				$table->setColAttrib(0, "width", $this->legendwidth);
			}
			foreach ( $this->elements as $key => $element){	
				
				if ( $element instanceof htmlwidget ){
					$elementname = $element->getname();
				} else {
					$elementname = '';
				}
				if ( method_exists($element, 'validate')){
					if ( ! $element->validate() ){
						$msg = new span($element->getErrorMessage());
						$msg->setclass('error');
						$table->row('', $msg );
					}
				}
				if ( isset($this->textforelements[$elementname])){
					$table->row('', $this->textforelements[$elementname]);				
				}
				if ( isset($this->legendStyle) && strlen($this->legendStyle)){
					$table->setCellAttrib('class', $this->legendStyle);
				}				
				if ( is_null($element)){
					$table->row($this->legends[$key], '');
				} elseif ( is_scalar($element) ){					
					if ((strlen($value) == 0) || empty($value) ){
						$table->row($this->legends[$key], '');
					} else {
						$table->row($this->legends[$key], $element);
					}
				} elseif ( $element instanceof htmlwidget ){
					$table->row($this->legends[$key], $element->getHtml());
				} elseif ( is_array($element) ){
					$table->row($this->legends[$key], join("", $element));
				} elseif ( is_object($element) && method_exists($element, '__toString') ){
					$table->row($this->legends[$key], $element->__toString());
				} else {
					$table->row($this->legends[$key], '');
				}
			

			}
		} elseif ( $this->layout == 'horizontal'){
			$table->newrow();	

			$temparr = array();			
			$counterrors = 0;		
			foreach ( $this->elements as $key => $element){	
				if ( method_exists($element, 'validate')){
					if ( $element->validate() ){
						$temparr[] = '';
					} else {
						$counterrors++;
						$msg = new span($element->getErrorMessage());
						$msg->setclass('error');
						$temparr[] = $msg;
					}
				}
			}				
			
			if ( $counterrors ){
				foreach ( $this->elements as $key => $element){	
					$table->col($temparr[$key]);				
				}
			}
				
			foreach ( $this->elements as $key => $element){	
				if ( $element instanceof htmlwidget ){
					$elementname = $element->getname();
				} else {
					$elementname = '';
				}
				if ( isset($this->textforelements[$elementname])){
					$table->col('');
				}
				if ( is_null($element)){
					$table->col($this->legends[$key]);
				} elseif ( is_scalar($element) ){					
					if ((strlen($value) == 0) || empty($value) ){
						$table->col($this->legends[$key]);
					} else {
						$table->col($this->legends[$key]);
					}
				} elseif ( $element instanceof htmlwidget ){
					$table->col($this->legends[$key]);
				} elseif ( is_array($element) ){
					$table->col($this->legends[$key]);
				} elseif ( is_object($element) && method_exists($element, '__toString') ){
					$table->col($this->legends[$key]);
				} else {
					$table->col($this->legends[$key]);
				}							
			}
			
			$table->setRowAttribs('valign', 'top');
			$table->newrow();
			foreach ( $this->elements as $key => $element){
				$elementname = $element->getname();
				if ( isset($this->textforelements[$elementname])){
					$table->col($this->textforelements[$elementname]);
				}
				if ( is_null($element)){
					$table->col( '');
				} elseif ( is_scalar($element) ){					
					if ((strlen($value) == 0) || empty($value) ){
						$table->col('');
					} else {
						$table->col($element);
					}
				} elseif ( $element instanceof htmlwidget ){
					$table->col($element->getHtml());
				} elseif ( is_array($element) ){
					$table->col(join("", $element));
				} elseif ( is_object($element) && method_exists($element, '__toString') ){
					$table->col( $element->__toString());
				} else {
					$table->col('');
				}				
										
			}
		}
		
		$this->html .= $table->getHtml();

		//any javascript for the form
		if( ! empty($this->javascript)){
			$this->html .= '<script language="JavaScript" type="text/javascript">';
			$this->html .= $this->javascript;
			$this->html .= '</script>';
		}

		//closing tag
		$this->html .= "</form>\n";
		return $this->html;
	}

	public function addJavaScript($script){
		$this->javascript .= "\n\n" . $script;
	}
	
	
	public function validate(){
		if ( empty($_POST)){
			return 1;
		} 
		
		
		foreach ($this->elements as $id => $question){
			if ( method_exists($question, 'validate')){			
				if (! $question->validate() ){
					$question->fail();
					$this->fail();
					return $this->isvalid();
				}
			}			
		}
		
		
		foreach ($this->hiddenElements as $id => $question){
			if ( method_exists($question, 'validate')){			
				if (! $question->validate() ){
					$question->fail();
					$this->fail();
					return $this->isvalid();
				}
			}			
		}		
		
		return $this->isvalid();
	}	
	
	public function getAnswer($nameofelement){
		foreach ($this->elements as $id => $element){
			if ( $element->getname() == $nameofelement){			
				return $element->getAnswer();				
			}			
		}
		return null;
	}
	
	public function fail(){
		$this->failed = 1;
	}

	public function isValid(){
		return ($this->failed == 0)? 1:0;
	}
}
?>